﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace PDFWriter
{
    public class DocumentPage : INode
    {
        public const string OBJECT_ID = "id";
        public const string GENERATION_ID = "gid";
        public const string PAGE = "Page";
        public const string DELIMETER = ":";
        private List<PDFObject> pageObjects = new List<PDFObject>();

        private string parentReference = "5 0 R";

        public string ParentReference
        {
            get { return parentReference; }
            set { parentReference = value; }
        }
        private string xmlString = "<Page id=\"1\">"+
        "<Resource id=\"3\">      " +
          "<Dictionary>"+
             "<DictionaryElement type=\"name\" value=\"ProcSet\">"+
               "<Array>"+
                 "<ArrayElement>/PDF</ArrayElement>"+
                 "<ArrayElement>/Text</ArrayElement>"+
               "</Array>"+
             "</DictionaryElement>"+
             "<DictionaryElement type=\"name\" value=\"Font\">"+
               "<Dictionary>"+
                 "<DictionaryElement type=\"name\" value=\"F1\"><ObjRef>4</ObjRef> </DictionaryElement>"+
              " </Dictionary>"+
             "</DictionaryElement>   "+
           "</Dictionary>"+
        "</Resource>"+
        "<Content id=\"2\">"+
            "<Dictionary>" +
              "<DictionaryElement type=\"name\" value=\"length\">51</DictionaryElement>"+
            "</Dictionary>"+
            "<Stream>"+
              "BT\n"+
              "/F1 24 Tf\n" +
              "1 0 0 1 260 600 Tm\n" +
              "(Hello World)Tj\n"+
              "ET\n"   +
            "</Stream>"           +
          "</Content>"        +
      "</Page>";

        public const string DOCUMENT_ROOT = "DocumentRoot";
        public const string MEDIA_BOX = "MediaBox";
        XmlDocument reader = new XmlDocument();

        public DocumentPage(string xmlString,string parentReference)
        {
            this.xmlString = xmlString;
            reader.LoadXml(xmlString);
            this.parentReference = parentReference;
        }

        public string ReferenceID
        {
            get;
            set;
        }

        public DocumentPage()
        {
            reader.LoadXml(xmlString);
        }

        public static string GetPageReference(XmlNode pageNode)
        {
            string reference = null;
            if (pageNode.Name == PAGE)
            {
               reference = pageNode.Attributes[OBJECT_ID].Value+" ";
                if (pageNode.Attributes[GENERATION_ID] != null)
                {
                    reference += pageNode.Attributes[GENERATION_ID].Value+" R";
                }else
                {
                    reference += "0 R";
                }
            }
            return reference;
        }

        //Later this can be delegated to PDFDictionary
        private StringBuilder GetPageDictionary()
        {
            StringBuilder pageDictionary = new StringBuilder();
            pageDictionary.Append("<<\n" + "/Type /Page\n/Parent "+ParentReference+"\n");            
            return pageDictionary;            
        }

        private string ProcessXML()
        { 
            StringBuilder builder = GetPageDictionary();
            reader.LoadXml(xmlString);
            PDFObject pdfObj = null;
            foreach (XmlNode node in reader.FirstChild.ChildNodes)
            {
                pdfObj = Utility.GetPDFObject(node.OuterXml);
                builder.Append("/"+pdfObj.ObjectType + " "+ pdfObj.ObjectID+"\n");
                pageObjects.Add(pdfObj);
            }
            builder.Append(">>\nendobj\n");
            string generationID = null;
            if (reader.FirstChild.Attributes[OBJECT_ID].Value != null)
            {
                generationID = reader.FirstChild.Attributes[OBJECT_ID].Value;
                if (reader.FirstChild.Attributes[GENERATION_ID] != null)
                {
                    generationID += reader.FirstChild.Attributes[GENERATION_ID].Value;
                }
                else
                {
                    generationID += " 0";
                }
                ReferenceID = generationID+" R";                
            }

            PDFObject pageObject = new PDFObject() { Text = generationID + " obj"+builder.ToString(), ObjectID = ReferenceID, ObjectType = PAGE };
            pageObjects.Add(pageObject);
            return pageObject.Text;
        }

        public static int GetPageCount(XmlNodeList xmlList)
        {
            byte pageCount = 0;
            foreach (XmlNode node in xmlList)
            {
                if (node.Name == PAGE)
                {
                    pageCount++;
                }
            }
            return pageCount;
        }

        public static string GetDocumentPageArray(XmlNodeList nodeList)
        {

            StringBuilder builder = new StringBuilder();
            builder.Append("[ ");
            foreach (XmlNode node in nodeList)
            {
                if (node.Name == PAGE)
                {
                    builder.Append(GetPageReference(node)+" ");
                }
            }
            builder.Append(" ]");
            return builder.ToString();
        }

        #region INode Members

        public PDFObject GetPDFObject()
        {
            throw new NotImplementedException();
        }

        public List<PDFObject> GetPDFObjects()
        {
            ProcessXML();
            return pageObjects;
        }

        #endregion
    }
}
